package com.example.meeting.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class RedisUtil {
    @Autowired
    private static RedisTemplate<String, Object> redisTemplate;

    public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    /**
     * 指定缓存失效时间
     * @param key 键
     * @param time 时间(秒)
     * @return
     */
    public static boolean expire(String key,Long time){
        try {
            if(time>0){
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
           log.error("redis指定缓存失效时间失败:"+e.getMessage());
        }
        return false;
    }

    /**
     * 根据key 获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public static Long getExpire(String key){
       try{
           return redisTemplate.getExpire(key,TimeUnit.SECONDS);
       }catch (Exception e){
           log.error("redis获取过期时间失败:"+e.getMessage());
       }
       return -1l;
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public static boolean hasKey(String key){
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {
            log.error("redis判断是否存在key失败:"+e.getMessage());
        }
        return false;
    }

    /**
     * 获取键对应的值
     */
    public static Object get(String key){
        Object value=null;
       try{
           value= redisTemplate.opsForValue().get(key);
       }catch(Exception e){
           log.error("获取redis值"+key+"失败:"+e.getMessage());
       }
       return value;
    }

    /**
     * 添加键值
     */
    public static void set(String key,Object value){
        try{
            redisTemplate.opsForValue().set(key,value);
        }catch (Exception e){
            log.error("redis设置值失败:"+e.getMessage());
        }
    }
    /**
     * 添加键值(含过期时间)
     */
    public static void set(String key,Object value,Long expire){
        try{
            redisTemplate.opsForValue().set(key,value,expire, TimeUnit.MILLISECONDS);
        }catch (Exception e){
            log.error("redis设置值失败:"+e.getMessage());
        }
    }

    /**
     * 添加zset集合数据
     */
    public static void zadd(String key,Object value,double score){
        try{
            redisTemplate.opsForZSet().add(key,value,score);
        }catch (Exception e){
            log.error("redis添加zset数据失败:"+e.getMessage());
        }
    }

    /**
     * 获取zset集合第一个元素
     */
    public static Set<Object> zget(String key,long start,long end){
        try{
            return redisTemplate.opsForZSet().range(key,start,end);
        }catch (Exception e){
            log.error("redis获取zset数据失败:"+e.getMessage());
        }
        return null;
    }

    /**
     * 获取zset指定元素的score
     */
    public static Double zscore(String key,Object value){
        try{
            return redisTemplate.opsForZSet().score(key,value);
        }catch (Exception e){
            log.error("redis获取zset指定元素score值失败:"+e.getMessage());
        }
        return null;
    }

    /**
     * 获取zset集合数量
     */
    public static Long zcount(String key){
        try{
            return redisTemplate.opsForZSet().size(key);
        }catch (Exception e){
            log.error("redis获取zset集合数量失败:"+e.getMessage());
        }
        return 0l;
    }

    /**
     * 删除zset指定元素
     */
    public static Long zremove(String key,Object value){
        try{
            return redisTemplate.opsForZSet().remove(key,value);
        }catch (Exception e){
            log.error("redis删除zset数据失败:"+e.getMessage());
        }
        return null;
    }

    /**
     * 删除对应键值
     */
    public static Boolean remove(String key){
        Boolean flag=false;
        try{
            flag=redisTemplate.delete(key);
        }catch (Exception e){
            log.error("redis键值删除失败:"+e.getMessage());
        }
        return flag;
    }

    /**
     * 递增值
     */

    public static void increment(String key){
        try{
            redisTemplate.opsForValue().increment(key);
        }catch (Exception e){
            log.error("redis递增值失败:"+e.getMessage());
        }
    }

    /**
     * 使用hash类型存储对象类型值
     */
    public static void setEntries(String key,Map<String,Object> entries,Integer time) throws Exception {
        try{
            redisTemplate.opsForHash().putAll(key,entries);
            //如果存在过期时间，则设置
            if (time!=null){
                redisTemplate.expire(key,time,TimeUnit.MINUTES);
            }
        }catch (Exception e){
            log.error("redis存储对象失败："+e.getMessage());
            throw new Exception("添加失败，请重试");
        }
    }

    /**
     * 从redis中获取hash类型对象值
     */
    public static Map<Object,Object> getEntries(String key) throws Exception {
        try{
            return redisTemplate.opsForHash().entries(key);
        }catch (Exception e){
            log.error("获取redis存储对象失败："+e.getMessage());
            throw new Exception("获取实体对象失败，请重试");
        }
    }

    /**
     * 执行lua脚本
     */
    public static String executeScript(DefaultRedisScript<Long> script, List<String> keys,String arg){
        try{
            return String.valueOf(redisTemplate.execute(script,keys,arg));
        }catch (Exception e){
            log.error("执行lua脚本出错："+e.getMessage());
        }
        return "-1";
    }
}

